/***************************************************
Class: GameApp
Includes: stdafx.h, Framework.h, Camera.h, Font.h, Light.h, Mesh.h, 
MiscObject.h, ProjObject.h, WorldObject.h, WorldTransformation.h
Editors: Gindi
Existing Issues: None
Description: The main part of the application. Here, updating, rendering, 
and handling input is where it all happens. Refer to the .cpp file(s) for 
more information on the function of the functions... :)
***************************************************/
#pragma once

#include "stdafx.h"
#include "Framework.h"
#include "Camera.h"
#include "Font.h"
#include "Light.h"
#include "Mesh.h"
#include "MiscObject.h"
#include "ProjObject.h"
#include "EnvObject.h"
#include "MarkerObject.h"
#include "Sound.h"
#include "WorldObject.h"
#include "WorldTransformation.h"
#include "Definitions.h"

class GameApp : public BaseApp
{
public:
	GameApp();
	~GameApp() { Release(); }
	void SetFramework(Framework* pFramework);
	bool Initialize();
	virtual void Release();
	virtual void OnCreateDevice(LPDIRECT3DDEVICE9 pDevice);
	virtual void OnResetDevice(LPDIRECT3DDEVICE9 pDevice);
	virtual void OnLostDevice();
	virtual void OnDestroyDevice();
	virtual void OnUpdateFrame(LPDIRECT3DDEVICE9 pDevice, float elapsedTime);
	virtual void OnRenderFrame(LPDIRECT3DDEVICE9 pDevice, float elapsedTime);
	virtual void ProcessInput(long changeInX, long changeInY, long chageInZ, bool* pMouseButtons, bool* pPressedKeys, float elapsedTime, HWND hWnd);
	virtual void setAA(bool a_AA);
	void OpenMap(LPDIRECT3DDEVICE9 pDevice, string file);

private:
	void InitializeCamera();
	void InitializeFonts(LPDIRECT3DDEVICE9 pDevice);
	void InitializeMuzzleFlashLights(LPDIRECT3DDEVICE9 pDevice);
	void InitializeLight(LPDIRECT3DDEVICE9 pDevice);
	void InitializeLightNV(LPDIRECT3DDEVICE9 pDevice);
	void InitializeGameMarkers(LPDIRECT3DDEVICE9 pDevice);

	void BeginScene(LPDIRECT3DDEVICE9 pDevice);
	void EndScene(LPDIRECT3DDEVICE9 pDevice);
	void RenderGround(LPDIRECT3DDEVICE9 pDevice);
	void RenderEnvObjects(LPDIRECT3DDEVICE9 pDevice);
	void RenderWorldObjects(LPDIRECT3DDEVICE9 pDevice);
	void RenderPlayer(LPDIRECT3DDEVICE9 pDevice);
	void RenderPlayerDirPoint(LPDIRECT3DDEVICE9 pDevice);
	void RenderProjectiles(LPDIRECT3DDEVICE9 pDevice);
	void RenderMiscObjects(LPDIRECT3DDEVICE9 pDevice);
	void RenderMarkerObjects(LPDIRECT3DDEVICE9 pDevice);
	void RenderText();
	void RenderLoading(LPDIRECT3DDEVICE9 pDevice);

	void displayPlayerHP();
	
	void UpdateHUD();
	void UpdateCamera();

	void UpdatePlayer(LPDIRECT3DDEVICE9 pDevice, float elapsedTime);
	void playerShoot(LPDIRECT3DDEVICE9 pDevice, float elapsedTime);
	void playerOutOfBounds(float elpasedTime);

	void UpdateProjectiles(LPDIRECT3DDEVICE9 pDevice, float elapsedTime);
	void DeleteProjectilesOutOfRange();
	void ProjectileCollision(LPDIRECT3DDEVICE9 pDevice);
	void UpdateProjectileMovement(float elapsedTime);

	void UpdateEnvObjects(LPDIRECT3DDEVICE9 pDevice);

	void UpdateNightVision(LPDIRECT3DDEVICE9 pDevice);
	void UpdateLights(LPDIRECT3DDEVICE9 pDevice);
	void UpdateMarkers(float elapsedTime);

	bool isOutOfBounds(D3DXVECTOR3* position);

	// start:ai stuff
	void UpdateAI(LPDIRECT3DDEVICE9 pDevice, float elapsedTime);
	void AIShoot(LPDIRECT3DDEVICE9 pDevice, float elapsedTime, WorldObject * wIter);

	ProjObject* createBullet(LPDIRECT3DDEVICE9 pDevice, WorldObject* srcUnit);
	ProjObject* createBomb(LPDIRECT3DDEVICE9 pDevice, WorldObject* srcUnit);
	void makePlayerMuzzleFlash(LPDIRECT3DDEVICE9 pDevice);
	void makeAiMuzzleFlash(LPDIRECT3DDEVICE9 pDevice, WorldObject* srcUnit);
	void makePlayerBombFlash(LPDIRECT3DDEVICE9 pDevice, ProjObject* pObj);
	void makeAiBombFlash(LPDIRECT3DDEVICE9 pDevice, ProjObject* pObj);

	void updateLook(WorldObject * wo, float elapsedTime);
	void setNewRandDest(WorldObject * wo ,float elapsedTime);
	D3DXVECTOR3 recalcRandPosOnMap();
	bool MakeAISmart(float elapsedTime, WorldObject * wo);
	D3DXVECTOR3 getDir(D3DXVECTOR3 initPos, D3DXVECTOR3 finalPos);
	bool isInTransitTowardsDest(WorldObject * wo);
	
	void calcAITargets();
	void updateAIMovement();

	// end:ai stuff

	void ParsePlayerData(LPDIRECT3DDEVICE9 pDevice, string dataFile);
	void ParseUnitData(ITERATOR(WorldObject) iter);
	void ParseEnvData(ITERATOR(EnvObject) iter);

	void setPlayerData(LPDIRECT3DDEVICE9 pDevice);
	void scaleDataToLevel(ITERATOR(WorldObject) iter);
	void addRandomancyToData(ITERATOR(WorldObject) iter);

private:
	Framework*			m_pFramework;
	Font				m_font;
	Font				m_smallFont;
	Font				m_mediumFont;
	Font				m_largeFont;
	Camera				m_camera;
	Light				m_lights[8];
	LPD3DXSPRITE		m_pTextSprite;
	INTPair				m_mousePosition;
	char				m_fps[10];
	char				m_objsRendered[25];
	char				m_loading[25];
	char				m_loadingDesc[70];
	char				m_outOfBoundsText[70];
	bool				m_AA;
	bool				m_leftMouseButton;
	bool				m_rightMouseButton;
	bool				m_TDView;
	bool				m_n;		// night-vision
	bool				slowmotion;		// slow motion
	int					m_objsRenderedCount;
	long				m_deltaX;
	long				m_deltaY;
	float				m_outOfBoundsTimer;
	// player stuff
	int careerScore;
	int credits;
	
	// lari
	D3DXVECTOR3			m_mapBoundsTL;
	D3DXVECTOR3			m_mapBoundsBR;

	// end:lari
	EnvObject			m_ground;
	WorldObject			m_player;
	PreGamePlayerInfo	m_playerInfo;
	WorldObject			m_playerDest;
	list<WorldObject>	m_lWorldObjects;
	list<EnvObject>		m_lEnvObjects;
	list<MiscObject>	m_lMiscObjects;
	list<MarkerObject>	m_lMarkerObjects;
	list<ProjObject>	m_lProjObjects;
	list<Sound>			m_lSound;
	ITERATOR(WorldObject)	wIter;
	ITERATOR(EnvObject)		eIter;
	ITERATOR(MiscObject)	mIter;
	ITERATOR(MarkerObject)	markIter;
	ITERATOR(ProjObject)	pIter;
	ITERATOR(Sound)			sIter;

	list<ITERATOR(WorldObject)>			to_deleteW;
	ITERATOR(ITERATOR(WorldObject))		t_dIterW;
	list<ITERATOR(ProjObject)>			to_deleteP;
	ITERATOR(ITERATOR(ProjObject))		t_dIterP;
	list<ITERATOR(MarkerObject)>		to_deleteMark;
	ITERATOR(ITERATOR(MarkerObject))	t_dIterMark;
};
